﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using EQEmu.Database;

namespace EQEmu.ZonePoints
{
    public class ZonePointsDatabase : ZonePoints, IDisposable
    {
        private EQEmuContext _context;

        public ZonePointsDatabase(string zone, EQEmuContextFactory factory, int zoneVersion = 0)
            :base(zone,zoneVersion)
        {
            _context = factory.Create();
            var query = _context.zone_points.Where(x => x.zone == zone && x.version == zoneVersion).ToArray();
            foreach (var zp in query)
            {
                var targetZone = FindZone((int)zp.target_zone_id);
                if (targetZone != null)
                {
                    zp.TargetZoneName = targetZone.short_name;
                }
                _points.Add(zp);
                zp.PropertyChanged += zp_PropertyChanged;
            }
        }

        private zone FindZone(int id)
        {
            var zone = _context.zone.FirstOrDefault(x => x.zoneidnumber == id);
            return zone;
        }

        private zone FindZone(string shortName)
        {
            var zone = _context.zone.FirstOrDefault(x => x.short_name == shortName);
            return zone;
        }

        void zp_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            var zp = sender as zone_points;
            if (zp == null) return;

            zone zone = null;           

            switch (e.PropertyName)
            {
                case "TargetZoneName":
                    zone = FindZone(zp.TargetZoneName);
                    if (zone != null && zp.target_zone_id != zone.zoneidnumber)
                    {
                        zp.target_zone_id = zone.zoneidnumber;
                    }
                    break;
                case "target_zone_id":
                    zone = FindZone((int)zp.target_zone_id);
                    if( zone != null && zp.TargetZoneName != zone.short_name )
                    {
                        zp.TargetZoneName = zone.short_name;
                    }
                    break;
                default:
                    break;
            }

        }

        public override bool HasModifications
        {
            get
            {
                if (_context != null)
                {
                    return _context.ObjectStateManager
                        .GetObjectStateEntries(
                            System.Data.EntityState.Added |
                            System.Data.EntityState.Deleted |
                            System.Data.EntityState.Modified).Any();
                }
                else return false;
            }
        }

        public override void AddPoint(zone_points zp)
        {
            base.AddPoint(zp);
            _context.zone_points.AddObject(zp);
        }

        public override zone_points CreatePoint()
        {
            var zp = _context.zone_points.CreateObject();
            zp.zone = ZoneShortName;
            zp.version = ZoneVersion;
            zp.PropertyChanged += zp_PropertyChanged;
            return zp;
        }

        public override void RemovePoint(zone_points zp)
        {
            base.RemovePoint(zp);
            zp.PropertyChanged -= zp_PropertyChanged;
            _context.zone_points.DeleteObject(zp);
        }

        protected void Dispose(bool disposeAll)
        {
            foreach (var zp in Points)
            {
                zp.PropertyChanged -= this.zp_PropertyChanged;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }
    }
}
